﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
using InkFx.WinControl.Core;
using InkFx.WinControl.Design;
using InkFx.WinControl.Utils;

namespace InkFx.WinControl
{
    /// <summary>
    /// 为可用作其他控件的容器的控件提供焦点管理功能。
    /// </summary>
    [ToolboxItem(false), Docking(DockingBehavior.Ask)]
    public class BaseSplitControl : System.Windows.Forms.ContainerControl, ISupportInitialize
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public BaseSplitControl()
        {
            SetStyle(Win32API.ControlStylesUAORSD, true);
            base.Margin = Padding.Empty;
            base.Padding = Padding.Empty;
        }


        #region  字 段 属 性

        /// <summary>
        /// 内部字段
        /// </summary>
        protected int m_SplitterWidth = 4;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Orientation m_Orientation = Orientation.Vertical;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected SplitterPanel m_Panel1 = null;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected SplitterPanel m_Panel2 = null;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected int m_Panel1MinSize = 25;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected int m_Panel2MinSize = 25;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_Panel1Collapsed = false;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_Panel2Collapsed = false;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected int m_Panel1Size = -1;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected int m_Panel2Size = -1;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_StopSplitter;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Color m_SplitterColor = Color.Transparent;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected FixedPanel m_FixedPanel = FixedPanel.None;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected static readonly object m_EventSplitterMoved = new object();
        /// <summary>
        /// 内部字段
        /// </summary>
        protected static readonly object m_EventSplitterMoving = new object();


        /// <summary>
        /// 获取或设置拆分器的宽度（以像素为单位）。
        /// <para>，它表示拆分器的宽度（以像素为单位）。默认值为四个像素。</para>
        /// <para>该值小于 1 或与方向不一致。1</para>
        /// </summary>
        [SRCategory("布局"), Localizable(true), DefaultValue(4)]
        public virtual int SplitterWidth
        {
            get
            {
                return this.m_SplitterWidth;
            }
            set
            {
                if (value == this.SplitterWidth) return;
                this.m_SplitterWidth = value;
                this.m_Panel2Size = -1;
                this.ResetRect();
                this.Invalidate();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [SRCategory("布局"), DefaultValue(Orientation.Vertical), Localizable(true)]
        public virtual Orientation Orientation
        {
            get
            {
                return this.m_Orientation;
            }
            set
            {
                if (this.m_Orientation == value) return;
                this.m_Orientation = value;
                this.m_Panel2Size = -1;
                this.ResetRect();
                this.Invalidate();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [SRCategory("布局"), DefaultValue(25), Localizable(true), RefreshProperties(RefreshProperties.All)]
        public virtual int Panel1MinSize
        {
            get
            {
                return this.m_Panel1MinSize;
            }
            set
            {
                if (value < 0) value = 0;
                if (value == this.Panel1MinSize) return;
                this.m_Panel1MinSize = value;
                this.ResetRect();
                this.Invalidate();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [SRCategory("布局"), DefaultValue(25), Localizable(true), RefreshProperties(RefreshProperties.All)]
        public virtual int Panel2MinSize
        {
            get
            {
                return this.m_Panel2MinSize;
            }
            set
            {
                if (value < 0) value = 0;
                if (value == this.Panel2MinSize) return;
                this.m_Panel2MinSize = value;
                this.ResetRect();
                this.Invalidate();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [SRCategory("布局"), DefaultValue(-1), Localizable(true), SettingsBindable(true)]
        public virtual int SplitterDistance
        {
            get
            {
                //如果有面板被折叠, 则  m_RectPanel1 的尺寸就不再是 分割尺寸
                if (this.Panel1Collapsed || this.Panel2Collapsed) return this.m_Panel1Size; 

                if (m_Orientation == Orientation.Horizontal)
                    return (m_RectPanel1.Height >= 1) ? m_RectPanel1.Height : this.m_Panel1Size;
                else
                    return (m_RectPanel1.Width >= 1) ? m_RectPanel1.Width : this.m_Panel1Size;
            }
            set
            {
                if (value < 0) value = 0;
                //if (value == this.SplitterDistance) return; //2020-12-09 注释本行代码, 必须调用一次 ResetRect() 函数

                this.m_Panel1Size = value;
                this.m_Panel2Size = -1;
                this.ResetRect();
                //this.Panel1.Bounds = m_RectPanel1;
                //this.Panel2.Bounds = m_RectPanel2;
                this.Invalidate();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [SRCategory("外观"), DefaultValue(typeof(Color), "Transparent"), Localizable(true), SettingsBindable(true)]
        public virtual Color SplitterColor
        {
            get { return this.m_SplitterColor; }
            set
            {
                this.m_SplitterColor = value;
                this.Invalidate();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual double SplitterDistanceRate
        {
            get
            {
                if (m_Panel1Size <= 0 || m_Panel2Size <= 0) this.ResetRect();
                return (m_Panel1Size <= 0 || m_Panel2Size <= 0) ? 0 : ((double)m_Panel1Size / (double)(m_Panel1Size + m_Panel2Size));
            }
            set
            {
                value = Math.Min(1, Math.Max(0, value));

                var size = this.ClientSize;
                if (this.Orientation == Orientation.Horizontal)
                    SplitterDistance = (int)Math.Round((size.Height - this.SplitterWidth) * value);
                else
                    SplitterDistance = (int)Math.Round((size.Width - this.SplitterWidth) * value);
            }
        }
        /// <summary>
        /// 获取或设置哪些控件边框停靠到其父控件并确定控件如何随其父级一起调整大小。
        /// </summary>
        [SRCategory("布局"), DefaultValue(DockStyle.None), Localizable(true), SettingsBindable(true)]
        public new virtual DockStyle Dock
        {
            get { return base.Dock; }
            set
            {
                base.Dock = value;
                this.ResetRect();
                this.Invalidate();
            } 
        }


        /// <summary>
        /// 
        /// </summary>
        [SRCategory("布局"), DefaultValue(false), Localizable(true), SettingsBindable(true)]
        public virtual bool Panel1Collapsed
        {
            get { return m_Panel1Collapsed; }
            set
            {
                if (value == this.Panel1Collapsed) return;
                m_Panel1Collapsed = value;
                if (m_Panel1Collapsed) m_Panel2Collapsed = false;
                this.ResetRect();
                this.Invalidate();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [SRCategory("布局"), DefaultValue(false), Localizable(true), SettingsBindable(true)]
        public virtual bool Panel2Collapsed
        {
            get { return m_Panel2Collapsed; }
            set
            {
                if (value == this.Panel2Collapsed) return;
                m_Panel2Collapsed = value;
                if (m_Panel2Collapsed) m_Panel1Collapsed = false;
                this.ResetRect();
                this.Invalidate();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public event SplitterEventHandler SplitterMoved
        {
            add { base.Events.AddHandler(m_EventSplitterMoved, value); }
            remove { base.Events.RemoveHandler(m_EventSplitterMoved, value); }
        }
        /// <summary>
        /// 
        /// </summary>
        public event SplitterCancelEventHandler SplitterMoving
        {
            add { base.Events.AddHandler(m_EventSplitterMoving, value); }
            remove { base.Events.RemoveHandler(m_EventSplitterMoving, value); }
        }



        /// <summary>
        /// 获取或设置在调整容器大小时将大小保持不变的  面板。
        /// <para> 值之一。默认值为 None。</para>
        /// <para>分配的值不是  值之一。2</para>
        /// </summary>
        [SRCategory("布局"), DefaultValue(FixedPanel.None)]
        public virtual FixedPanel FixedPanel
        {
            get { return this.m_FixedPanel; }
            set
            {
                //if (this.m_FixedPanel == value) return; //2020-12-09 注释本行代码, 必须调用一次 ResetRect() 函数
                this.m_FixedPanel = value;
                this.ResetRect();
            }
        }
        /// <summary>
        /// 返回 被固定尺寸 的那个 Panel 的尺寸
        /// <para>如果 FixedPanel==Panel2, 则返回 Panel2 的尺寸, 否则返回 Panel1 的尺寸</para>
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual int FixedPanelSize
        {
            get
            {
                if (FixedPanel == FixedPanel.Panel2) { return m_Panel2Size; }
                return m_Panel1Size;
            }
            set
            {
                var bound = new Rectangle(Point.Empty, this.Size);  //这里不能用 var bound = this.Bounds;
                var orientation = this.Orientation;
                var splitterWidth = this.SplitterWidth;
                var size = (orientation == Orientation.Horizontal) ? bound.Height : bound.Width;

                if (FixedPanel == FixedPanel.Panel2) { m_Panel2Size = value; m_Panel1Size = size - splitterWidth - value; }
                else { m_Panel1Size = value; m_Panel2Size = size - splitterWidth - value; }

                this.ResetRect();
                this.Invalidate();
            }
        }

        /// <summary>
        /// 获取或设置当鼠标指针位于控件上时显示的光标。
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public override Cursor Cursor
        {
            get { return base.Cursor; }
            set { base.Cursor = value; }
        }
        /// <summary>
        /// 当前分割线 是否正在移动中 (即; 当前是否正在执行 分割线的拖拽)
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual bool IsSplitMoving
        {
            get { return m_Splitter != null && m_Splitter.IsSplitMoving; }
        }
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        protected virtual bool AlwaysShowSplitter
        {
            get { return false; }
        }
        /// <summary>
        /// 当前控件是否是 横向分割 (本属性是 Orientation 的 中转属性)
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public virtual bool IsHorizontal
        {
            get { return this.Orientation == Orientation.Horizontal; }
            set { this.Orientation = (value) ? Orientation.Horizontal : Orientation.Vertical; }
        }

        /// <summary>
        /// 
        /// </summary>
        [Localizable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public SplitterPanel Panel1
        {
            get
            {
                if (m_Panel1 == null) this.InitPanel12();
                return m_Panel1;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [Localizable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public SplitterPanel Panel2
        {
            get
            {
                if (m_Panel1 == null) this.InitPanel12();
                return m_Panel2;
            }
        }
        /// <summary>
        /// 获取包含在控件内的控件的集合。
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new ControlCollection Controls
        {
            get { return base.Controls; }
        }

        #endregion


        #region  函 数 改 写

        /// <summary>
        /// 延迟触发 base.Invalidate() 函数
        /// </summary>
        public virtual void Invalidate()
        {
            GUIHelper.Invalidate(this);
        }


        /// <summary>
        /// 引发 System.Windows.Forms.Control.SizeChanged 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.EventArgs。</param>
        protected override void OnSizeChanged(EventArgs e)
        {
            this.ResetRect();
            base.OnSizeChanged(e);
            this.Invalidate();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: SplitterEventArgs</param>
        protected virtual void OnSplitterMoved(SplitterEventArgs e)
        {
            SplitterEventHandler handler = this.Events[m_EventSplitterMoved] as SplitterEventHandler;
            if (handler != null) handler((object)this, e);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: SplitterCancelEventArgs</param>
        protected virtual void OnSplitterMoving(SplitterCancelEventArgs e)
        {
            SplitterCancelEventHandler handler = this.Events[m_EventSplitterMoving] as SplitterCancelEventHandler;
            if (handler != null) handler((object)this, e);
        }
        /// <summary>
        /// 引发 System.Windows.Forms.Control.MouseMove 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.MouseEventArgs。</param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            var point = e.Location;
            var orientation = this.Orientation;

            if (IsSplitMoving)
            {
                SetCursor(orientation == Orientation.Horizontal ? Cursors.HSplit : Cursors.VSplit);

                var rect = SplitterRectangle;
                var info = m_Splitter.GetSplitInfo();
                var diff = info.Diff;
                OnSplitterMoving(new SplitterCancelEventArgs(e.X, e.Y, rect.X + diff.X, rect.Y + diff.Y));
                DrawSplitter();
            }
            else if (!this.Panel1Collapsed && !this.Panel2Collapsed)
                SetCursor(this.SplitterRectangle.Contains(point) ? ((orientation == Orientation.Horizontal) ? Cursors.HSplit : Cursors.VSplit) : null);
        }
        /// <summary>
        /// 引发 System.Windows.Forms.Control.MouseDown 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.MouseEventArgs。</param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (!m_StopSplitter && !this.Panel1Collapsed && !this.Panel2Collapsed)
            {
                var rectangle = this.SplitterRectangle;
                if (rectangle.Contains(e.Location)) { BeginSplitter(m_RectSplitRange, rectangle); }
            }
        }
        /// <summary>
        /// 引发 System.Windows.Forms.Control.MouseUp 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.MouseEventArgs。</param>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (IsSplitMoving)
            {
                var rect = SplitterRectangle;
                var info = EndSplitter();
                var diff = info.Diff;
                DoSplitMoved(info);
                this.ResetRect();
                OnSplitterMoved(new SplitterEventArgs(e.X, e.Y, rect.X + diff.X, rect.Y + diff.Y));
            }
        }
        /// <summary>
        /// 引发 System.Windows.Forms.Control.MouseLeave 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.EventArgs。</param>
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            SetCursor(null);
        }
        
        /// <summary>
        /// 引发 System.Windows.Forms.Control.HandleCreated 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.EventArgs。</param>
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            if (m_Panel1 == null || m_Panel2 == null) this.InitPanel12();
            this.ResetRect();
        }
        /// <summary>
        /// 引发 System.Windows.Forms.Control.Paint 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.PaintEventArgs。</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                base.OnPaint(e);
                this.OnPaintSplitter(e);
            }
            catch (Exception ex) { Tools.LogWarn2(ex, "改写 BaseSplitControl.OnPaint(PaintEventArgs e) 发生错误"); }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: PaintEventArgs</param>
        public virtual void OnPaintSplitter(PaintEventArgs e)
        {
            var color = ColorHelper.BlendColor(this.BackColor, this.SplitterColor);
            if (!GUIHelper.IsEmptyColor(color)) GUIHelper.FillBack(e.Graphics, color, this.SplitterRectangle, this.Enabled);
            else if (DesignMode) { GUIHelper.FillBack(e.Graphics, Color.FromArgb(100, Color.Black), this.SplitterRectangle, this.Enabled); }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender">Type: object</param>
        /// <param name="e">Type: EventArgs</param>
        protected virtual void OnPanel1BackColorChanged(object sender, EventArgs e)
        {
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender">Type: object</param>
        /// <param name="e">Type: EventArgs</param>
        protected virtual void OnPanel1ForeColorChanged(object sender, EventArgs e)
        {
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender">Type: object</param>
        /// <param name="e">Type: EventArgs</param>
        protected virtual void OnPanel2BackColorChanged(object sender, EventArgs e)
        {
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender">Type: object</param>
        /// <param name="e">Type: EventArgs</param>
        protected virtual void OnPanel2ForeColorChanged(object sender, EventArgs e)
        {
        }

        #endregion


        #region  坐 标 区 域


        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectFull = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectMin = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectPanel1 = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectPanel2 = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectSplitter = Rectangle.Empty;

        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual Rectangle RectPanel1
        {
            get { return m_RectPanel1; }
        }
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual Rectangle RectPanel2
        {
            get { return m_RectPanel2; }
        }
        /// <summary>
        /// 获取分割条 相对控件本身的 最终区域
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual Rectangle SplitterRectangle
        {
            get { return m_RectSplitter; }
        }



        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_ResetRect = false;
        /// <summary>
        /// 
        /// </summary>
        public virtual void ResetRect()
        {
            var panel1 = this.m_Panel1;
            var panel2 = this.m_Panel2;
            if (panel1 == null || panel2 == null) return;
            //if (!this.IsHandleCreated) return;

            var bound = new Rectangle(Point.Empty, this.Size);  //这里不能用 var bound = this.Bounds;
            var fixedPanel = this.FixedPanel;
            var orientation = this.Orientation;
            var splitterWidth = this.SplitterWidth;
            var panel1MinSize = this.Panel1MinSize;
            var panel2MinSize = this.Panel2MinSize;
            var panel1Collapsed = this.Panel1Collapsed;
            var panel2Collapsed = this.Panel2Collapsed;
            var panel1Size = this.m_Panel1Size;
            var panel2Size = this.m_Panel2Size;
            var showSplitter = this.AlwaysShowSplitter;
            if (bound.Width <= 0 || bound.Height <= 0) return;
            //if (this.Parent == null) return;

            if (m_ResetRect) return;

            try
            {
                m_ResetRect = true;
                this.SuspendLayout();
                panel1.SuspendLayout();
                panel2.SuspendLayout();

                if (orientation == Orientation.Horizontal)
                {
                    #region  上 下 分 割

                    m_RectMin = new Rectangle(bound.X, bound.Y, bound.Width, splitterWidth + panel1MinSize + panel2MinSize);
                    m_RectFull = new Rectangle(bound.X, bound.Y, bound.Width, bound.Height);

                    if (panel2Size < 0) panel2Size = m_Panel2Size = bound.Height - splitterWidth - panel1Size;

                    int height1 = 0, height2 = 0, heightS = splitterWidth;
                    if (fixedPanel == FixedPanel.Panel1) { height1 = panel1Size; }
                    else if (fixedPanel == FixedPanel.Panel2) { height1 = bound.Height - splitterWidth - panel2Size; }
                    else if (fixedPanel == FixedPanel.None)
                    {
                        double rate = (m_Panel1Size <= 0 || m_Panel2Size <= 0) ? -1 : (double)m_Panel1Size / (double)(m_Panel1Size + m_Panel2Size);
                        height1 = (rate < 0 || rate > 1) ? panel1Size : (int)Math.Ceiling((bound.Height - splitterWidth) * rate);
                    }
                    height2 = bound.Height - height1 - heightS;

                    if (height1 < m_Panel1MinSize) { height1 = m_Panel1MinSize; height2 = bound.Height - height1 - heightS; }
                    if (height2 < m_Panel2MinSize) { height2 = m_Panel2MinSize; height1 = bound.Height - height2 - heightS; }
                    if (height1 < m_Panel1MinSize) { height1 = m_Panel1MinSize; }


                    this.m_StopSplitter = (height1 + height2 + heightS) > bound.Height;
                    m_RectPanel1 = new Rectangle(0, 0, bound.Width, height1);
                    m_RectSplitter = new Rectangle(0, m_RectPanel1.Bottom, bound.Width, splitterWidth);
                    m_RectPanel2 = new Rectangle(0, m_RectSplitter.Bottom, bound.Width, height2);

                    if (panel1Collapsed)
                    {
                        if (showSplitter) { m_RectPanel1 = Rectangle.Empty; m_RectSplitter = new Rectangle(0, 0, m_RectFull.Width, splitterWidth); m_RectPanel2 = new Rectangle(0, splitterWidth, m_RectFull.Width, m_RectFull.Height - splitterWidth); }
                        else { m_RectPanel1 = Rectangle.Empty; m_RectSplitter = Rectangle.Empty; m_RectPanel2 = m_RectFull; }
                    }
                    if (panel2Collapsed)
                    {
                        if (showSplitter) { m_RectPanel2 = Rectangle.Empty; m_RectSplitter = new Rectangle(0, m_RectFull.Height - splitterWidth, m_RectFull.Width, splitterWidth); m_RectPanel1 = new Rectangle(0, 0, m_RectFull.Width, m_RectFull.Height - splitterWidth); }
                        else { m_RectPanel2 = Rectangle.Empty; m_RectSplitter = Rectangle.Empty; m_RectPanel1 = m_RectFull; }
                    }

                    m_RectSplitRange = (m_RectSplitter.Width <= 0 || m_RectSplitter.Height <= 0) ? Rectangle.Empty : new Rectangle(0, m_Panel1MinSize, bound.Width, bound.Height - m_Panel1MinSize - m_Panel2MinSize);


                    m_Panel1.Bounds = m_RectPanel1;
                    m_Panel2.Bounds = m_RectPanel2;

                    #endregion
                }
                else
                {
                    #region  左 右 分 割

                    m_RectMin = new Rectangle(bound.X, bound.Y, splitterWidth + panel1MinSize + panel2MinSize, bound.Height);
                    m_RectFull = new Rectangle(bound.X, bound.Y, bound.Width, bound.Height);

                    if (panel2Size < 0) panel2Size = m_Panel2Size = bound.Width - splitterWidth - panel1Size;


                    int width1 = 0, width2 = 0, widthS = splitterWidth;
                    if (fixedPanel == FixedPanel.Panel1) { width1 = panel1Size; }
                    else if (fixedPanel == FixedPanel.Panel2) { width1 = bound.Width - splitterWidth - panel2Size; }
                    else if (fixedPanel == FixedPanel.None)
                    {
                        double rate = (m_Panel1Size <= 0 || m_Panel2Size <= 0) ? -1 : (double)m_Panel1Size / (double)(m_Panel1Size + m_Panel2Size);
                        width1 = (rate < 0 || rate > 1) ? panel1Size : (int)Math.Ceiling((bound.Width - splitterWidth) * rate);
                    }
                    width2 = bound.Width - width1 - widthS;

                    if (width1 < m_Panel1MinSize) { width1 = m_Panel1MinSize; width2 = bound.Width - width1 - widthS; }
                    if (width2 < m_Panel2MinSize) { width2 = m_Panel2MinSize; width1 = bound.Width - width2 - widthS; }
                    if (width1 < m_Panel1MinSize) { width1 = m_Panel1MinSize; }


                    this.m_StopSplitter = (width1 + width2 + widthS) > bound.Width;
                    m_RectPanel1 = new Rectangle(0, 0, width1, bound.Height);
                    m_RectSplitter = new Rectangle(m_RectPanel1.Right, 0, splitterWidth, bound.Height);
                    m_RectPanel2 = new Rectangle(m_RectSplitter.Right, 0, width2, bound.Height);

                    if (panel1Collapsed)
                    {
                        if (showSplitter) { m_RectPanel1 = Rectangle.Empty; m_RectSplitter = new Rectangle(0, 0, splitterWidth, m_RectFull.Height); m_RectPanel2 = new Rectangle(splitterWidth, 0, m_RectFull.Width - splitterWidth, m_RectFull.Height); }
                        else { m_RectPanel1 = Rectangle.Empty; m_RectSplitter = Rectangle.Empty; m_RectPanel2 = m_RectFull; }
                    }
                    if (panel2Collapsed)
                    {
                        if (showSplitter) { m_RectPanel2 = Rectangle.Empty; m_RectSplitter = new Rectangle(m_RectFull.Width - splitterWidth, 0, splitterWidth, m_RectFull.Height); m_RectPanel1 = new Rectangle(0, 0, m_RectFull.Width - splitterWidth, m_RectFull.Height); }
                        else { m_RectPanel2 = Rectangle.Empty; m_RectSplitter = Rectangle.Empty; m_RectPanel1 = m_RectFull; }
                    }

                    m_RectSplitRange = (m_RectSplitter.Width <= 0 || m_RectSplitter.Height <= 0) ? Rectangle.Empty : new Rectangle(m_Panel1MinSize, 0, bound.Width - m_Panel1MinSize - m_Panel2MinSize, bound.Height);


                    if (m_RectPanel1.Width <= 0 || m_RectPanel1.Height <= 0) { m_Panel1.Visible = false; }
                    else { if (m_Panel1.Bounds != m_RectPanel1) { m_Panel1.Bounds = m_RectPanel1; } if (!m_Panel1.Visible) { m_Panel1.Visible = true; } }
                    if (m_RectPanel2.Width <= 0 || m_RectPanel2.Height <= 0) { m_Panel2.Visible = false; }
                    else { if (m_Panel2.Bounds != m_RectPanel2) { m_Panel2.Bounds = m_RectPanel2; } if (!m_Panel2.Visible) { m_Panel2.Visible = true; } }

                    #endregion
                }
            }
            finally
            {
                panel1.ResumeLayout();
                panel2.ResumeLayout();
                this.ResumeLayout();
                this.PerformLayout();
                m_ResetRect = false;
            }

            //if (this.DesignMode) { MessageBox.Show(this.m_Panel1Size + " | " + this.m_Panel2Size); }
        }
        /// <summary>
        /// 
        /// </summary>
        protected virtual void InitPanel12()
        {
            if (m_Panel1 == null) { m_Panel1 = new SplitterPanel(this); this.Controls.Add(m_Panel1); }
            if (m_Panel2 == null) { m_Panel2 = new SplitterPanel(this); this.Controls.Add(m_Panel2); }

            m_Panel1.BackColorChanged += OnPanel1BackColorChanged;
            m_Panel1.ForeColorChanged += OnPanel1ForeColorChanged;
            m_Panel2.BackColorChanged += OnPanel2BackColorChanged;
            m_Panel2.ForeColorChanged += OnPanel2ForeColorChanged;
        }

        #endregion


        #region  分 割 拖 拽

        /// <summary>
        /// 内部字段
        /// </summary>
        protected SplitterForm m_Splitter;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectSplitRange = Rectangle.Empty;


        /// <summary>
        /// 
        /// </summary>
        /// <param name="rectRange">Type: Rectangle</param>
        /// <param name="rectSplit">Type: Rectangle</param>
        protected virtual void BeginSplitter(Rectangle rectRange, Rectangle rectSplit)
        {
            var rectSplit2 = this.RectangleToScreen(rectSplit);
            var clip = this.GetClipRegion();

            if (m_Splitter == null) { m_Splitter = SplitterForm.BeginSplitter(this.FindForm(), this.IsHorizontal, this.RectangleToScreen(rectRange), rectSplit2, clip); }
            m_Splitter.ShowSplitter(rectSplit2, clip);
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual void DrawSplitter()
        {
            if (m_Splitter != null) m_Splitter.ShowSplitter();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual SplitInfo EndSplitter()
        {
            if (m_Splitter != null)
            {
                var result = m_Splitter.EndSplitter();
                m_Splitter = null;
                return result;
            }
            return SplitInfo.Empty;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual SplitInfo GetSplitInfo()
        {
            var info = (m_Splitter != null) ? m_Splitter.GetSplitInfo() : SplitInfo.Empty;
            var info2 = new SplitInfo(this.RectangleToClient(info.Start), this.RectangleToClient(info.End));
            return info2;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected virtual Region GetClipRegion()
        {
            var clip = Win32API.GetClipRegion(this);
            return clip;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="info">Type: SplitInfo</param>
        protected virtual void DoSplitMoved(SplitInfo info)
        {
            var diff = info.Diff;
            if (diff.X == 0 && diff.Y == 0) return;

            var bound = new Rectangle(Point.Empty, this.Size);  //这里不能用 var bound = this.Bounds;
            var orientation = this.Orientation;
            var splitterWidth = this.SplitterWidth;

            this.m_Panel1.SuspendLayout();
            this.m_Panel2.SuspendLayout();

            if (orientation == Orientation.Horizontal)
            {
                this.m_Panel1.Height = this.m_Panel1.Height + diff.Y;
                this.m_Panel2.Height = bound.Height - splitterWidth - this.m_Panel1.Height;
                m_Panel1Size = this.m_Panel1.Height;
                m_Panel2Size = this.m_Panel2.Height;
            }
            else if (orientation == Orientation.Vertical)
            {
                this.m_Panel1.Width = this.m_Panel1.Width + diff.X;
                this.m_Panel2.Width = bound.Width - splitterWidth - this.m_Panel1.Width;
                m_Panel1Size = this.m_Panel1.Width;
                m_Panel2Size = this.m_Panel2.Width;
            }

            this.ResetRect();

            this.m_Panel1.ResumeLayout();
            this.m_Panel2.ResumeLayout();
            //Win32API.ReSetWindowPos(this.m_Panel1.Handle);
            //Win32API.ReSetWindowPos(this.m_Panel2.Handle);
            this.m_Panel1.OnSize2Changed(EventArgs.Empty);
            this.m_Panel2.OnSize2Changed(EventArgs.Empty);
        }

        #endregion



        #region  其 他 函 数

        /// <summary>
        /// 内部字段
        /// </summary>
        protected Cursor m_BakCursor = null;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="cursor">Type: System.Windows.Forms.Cursor</param>
        protected void SetCursor(System.Windows.Forms.Cursor cursor)
        {
            if (m_BakCursor == null) m_BakCursor = base.Cursor ?? Cursors.Default;
            var baseCursor = base.Cursor;
            if (baseCursor != null && baseCursor != cursor)
                base.Cursor = cursor ?? m_BakCursor;
        }


        /// <summary>
        /// 用信号通知对象初始化即将开始。
        /// </summary>
        public virtual void BeginInit()
        {
        }
        /// <summary>
        /// 用信号通知对象初始化已完成。
        /// </summary>
        public virtual void EndInit()
        {
            this.ResetRect();
        }

        #endregion
    }


    /// <summary>
    /// 用于对控件集合进行分组。
    /// </summary>
    [ToolboxItem(false)]
    public class SplitterPanel : SimpPanel  //System.Windows.Forms.Panel //
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="owner">Type: InkFx.WinControl.BaseSplitControl</param>
        public SplitterPanel(InkFx.WinControl.BaseSplitControl owner)
        {
            SetStyle(Win32API.ControlStylesUAORSD, true);
            base.ResizeRedraw = true;
            m_Owner = owner;
        }

        /// <summary>
        /// 内部字段
        /// </summary>
        protected InkFx.WinControl.BaseSplitControl m_Owner;
        /// <summary>
        /// 
        /// </summary>
        public InkFx.WinControl.BaseSplitControl Owner
        {
            get { return this.m_Owner; }
        }

        /// <summary>
        /// 获取或设置控件的高度和宽度。
        /// </summary>
        [Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), EditorBrowsable(EditorBrowsableState.Never)]
        public new Size Size
        {
            get { return base.Size; }
            set { base.Size = value; }
        }



        //protected override CreateParams CreateParams
        //{
        //    get
        //    {
        //        CreateParams cp = base.CreateParams;
        //        cp.ExStyle |= (int)WindowStyles.WS_CLIPCHILDREN; //此参数 存在严重BUG
        //        return cp;
        //    }
        //}
    }

}

